import json
import os
from jose.backends import base
from pydantic import BaseModel
from typing import Dict, List, Optional, Dict, Literal

class MCPServerConfig(BaseModel):
    autoApprove: List[str] = []
    disabled: Optional[bool] = None
    timeout: int = 60
    command: Optional[str] = None
    args: Optional[List[str]] = None
    env: Optional[Dict] = None
    url: Optional[str] = None
    transportType: str

class ModelParameter(BaseModel):
    provider: str
    model: str
    title: str
    base_url: Optional[str]=None 
    api_key: Optional[str]=None
    max_retries: Optional[int] = 3 
    client: Optional[str]=None
    keep_alive_seconds: Optional[str] = None
    temperature: Optional[float] = None
    top_k: Optional[int] = None
    top_p: Optional[float] = None
    max_tokens: Optional[int] = None
    systemMessage: Optional[str] = None 
    contextLength: Optional[int]=None, # type: ignore
    repetition_penalty: Optional[float] = None
    maxCompletionTokens: Optional[int]=None
    stream_options: Optional[object]= None 
    extra_body: Optional[object]= None
    dimension: Optional[int] = None # 嵌入维度

class AgentConfig(BaseModel):
    max_iterations: int = 2
    mcp_config: MCPServerConfig
    model_parameter: ModelParameter

class EmbeddingConfig(BaseModel):
    provider: Literal["ollama", "openai"] = "ollama"
    base_url: Optional[str]="http://localhost:11434"
    model: str = "mxbai-embed-large:335m"  # Ollama 嵌入模型
    dimension: int = 1024
    api_key: Optional[str] = None
class PostgresConfigurationSettings(BaseModel):
    """PostgreSQL配置设置"""
    max_connections: int = 20
    statement_cache_size: int = 100

class QueryConfig(BaseModel):
    """查询配置设置"""
    top_k: int = 5
    similarity_threshold: float = 0.001

class DatabaseConfig(BaseModel):
    provider: Literal["postgres"] = "postgres"
    driver: Literal["postgres"] = "postgres"
    host: str = os.getenv("PGHOST", "localhost")
    port: int = int(os.getenv("PGPORT", "5432"))
    db_name: str = os.getenv("PGDATABASE", "scorpio")
    user: str = os.getenv("PGUSER", "postgres")
    password: str = os.getenv("PGPASSWORD", "postgres")
    #schema: str = "public"
    config_settings: Optional[PostgresConfigurationSettings] = None

DEFAULT_CONF_PATH=os.getcwd()+'/scorpio_config.json'
SESSION_DATA_FILE = "session_data.bin"
class ScorpioConfig(BaseModel):
    project_name: str = "scorpio"
    default_model: Optional[str]=None
    default_provider: Optional[str]=None
    environment: str = os.getenv("SCORPIO_ENV", "development")  # 默认为开发环境
    mcp_servers: Dict[str, MCPServerConfig]
    models: List[ModelParameter]
    embedding: Optional[EmbeddingConfig]=None
    database: Optional[DatabaseConfig]=None
    query: Optional[QueryConfig]=None

    def get_model(self, provider: str, model: str)->ModelParameter:
        model_param=self.models[0]
        if provider:
            hash_models={}
            found=False
            for item in self.models:
                if hash_models.get(item.provider):
                    hash_models[item.provider].append(item)
                else:
                    hash_models[item.provider]=[item]
                if item.model==model and item.provider==provider:
                    model_param=item
                    found=True
                    break
            if not found and model_param.provider != provider:
                model_param=hash_models[provider][0]
        return model_param
    
    def get_default_model(self)->ModelParameter:
        return self.get_model(self.default_provider, self.default_model) 


_config_instance: Optional[ScorpioConfig] = None

def get_config()->ScorpioConfig | None:
    global _config_instance
    config_path=os.getenv('SCORPIO_CONF') or DEFAULT_CONF_PATH
    if _config_instance is None:
        try:
            with open(config_path) as f:
                config_data = json.load(f)
            _config_instance = ScorpioConfig(**config_data)
            if _config_instance.database is None:
                db_config=DatabaseConfig()
                if db_config.config_settings is None:
                    db_config.config_settings=PostgresConfigurationSettings()
                _config_instance.database=db_config
                
            if _config_instance.embedding is None:
                _config_instance.embedding=EmbeddingConfig()
            
            if _config_instance.query is None:
                _config_instance.query=QueryConfig()
                
        except FileNotFoundError:
            raise RuntimeError("未找到配置文件scorpio_config.json")
    else: pass
    # print(f"database configure: {_config_instance.database}")
    return _config_instance

def reload_config():
    """重新加载配置（用于热更新）"""
    global _config_instance
    _config_instance = None
    return get_config()

def close_config():
    """关闭配置并清理资源"""
    global _config_instance
    if _config_instance:
        # 执行任何必要的清理操作
        _config_instance = None

